﻿#region using statements

using System;

using Microsoft.Xna.Framework;

using NGen;
using NGen.Managers.Audio;
using NGen.Managers.GUI;

using Nuclex.UserInterface;
using Nuclex.UserInterface.Controls;
using Nuclex.UserInterface.Controls.Desktop;

#endregion

namespace XNAGameDemo.GUI
{
	internal class GUIElementSettings : GUIElement
	{
		#region local fields

		private readonly ButtonControl m_audioButton = new ButtonControl();

		private readonly LabelControl m_audioMusicValueLabel1 = new LabelControl();

		private readonly LabelControl m_audioMusicValueLabel2 = new LabelControl();

		private readonly HorizontalSliderControl m_audioMusicVolumeSlider = new HorizontalSliderControl();

		private readonly LabelControl m_audioSoundValueLabel1 = new LabelControl();

		private readonly LabelControl m_audioSoundValueLabel2 = new LabelControl();

		private readonly HorizontalSliderControl m_audioSoundVolumeSlider = new HorizontalSliderControl();

		private readonly ButtonControl m_backMainButton = new ButtonControl();

		private readonly ButtonControl m_gameplayButton = new ButtonControl();

		private readonly ButtonControl m_otherBackButton = new ButtonControl();

		private readonly LabelControl m_videoAntialiasingLabel = new LabelControl();

		private readonly ListControl m_videoAntialiasingList = new ListControl();

		private readonly ButtonControl m_videoApplyButton = new ButtonControl();

		private readonly ButtonControl m_videoButton = new ButtonControl();

		private readonly OptionControl m_videoFullscreenOption = new OptionControl();

		private readonly LabelControl m_videoResolutionLabel = new LabelControl();

		private readonly ListControl m_videoResolutionList = new ListControl();

		private readonly OptionControl m_videoVsyncOption = new OptionControl();

		private readonly WindowControl m_window = new WindowControl();

		#endregion

		#region local methods

		private void _ConfigureMainWindow(object p_sender, EventArgs p_e) {
			m_window.Children.Clear();
			m_window.Children.Add(m_backMainButton);
			m_window.Children.Add(m_audioButton);
			m_window.Children.Add(m_videoButton);
			m_window.Children.Add(m_gameplayButton);
		}

		private void _ConfigureAudioWindow(object p_sender, EventArgs p_e) {
			m_window.Children.Clear();
			m_window.Children.Add(m_otherBackButton);
			m_window.Children.Add(m_audioMusicVolumeSlider);
			m_window.Children.Add(m_audioSoundVolumeSlider);
		}

		private void _ConfigureVideoWindow(object p_sender, EventArgs p_e) {
			m_window.Children.Clear();
			m_window.Children.Add(m_otherBackButton);
			m_window.Children.Add(m_videoResolutionLabel);
			m_window.Children.Add(m_videoResolutionList);
			m_videoResolutionList.SelectedItems.Clear();
			switch(GameEngine.GraphicsDeviceManager.PreferredBackBufferWidth) {
				case 800:
					m_videoResolutionList.SelectedItems.Add(0);
					break;
				case 1280:
					m_videoResolutionList.SelectedItems.Add(1);
					break;
				case 1440:
					m_videoResolutionList.SelectedItems.Add(2);
					break;
			}
			m_window.Children.Add(m_videoFullscreenOption);
			m_videoFullscreenOption.Selected = GameEngine.GraphicsDeviceManager.IsFullScreen;
			m_window.Children.Add(m_videoVsyncOption);
			m_videoVsyncOption.Selected = GameEngine.GraphicsDeviceManager.SynchronizeWithVerticalRetrace;
			m_window.Children.Add(m_videoAntialiasingList);
			m_window.Children.Add(m_videoAntialiasingLabel);
			m_videoAntialiasingList.SelectedItems.Clear();
			m_videoAntialiasingList.SelectedItems.Add(GameEngine.GraphicsDeviceManager.GraphicsDevice.PresentationParameters.MultiSampleCount == 0 ? 0 : (int) (Math.Log(GameEngine.GraphicsDeviceManager.GraphicsDevice.PresentationParameters.MultiSampleCount) / Math.Log(2)));

			m_window.Children.Add(m_videoApplyButton);
		}

		private void _ConfigureGameplayWindow(object p_sender, EventArgs p_e) {
			m_window.Children.Clear();
			m_window.Children.Add(m_otherBackButton);
		}

		private void _MusicSliderMoved(object p_sender, EventArgs p_e) {
			GameEngine.GetService<IManagerAudio2D>().SongVolume = m_audioMusicVolumeSlider.ThumbPosition;
			m_audioMusicValueLabel2.Text = Math.Floor(GameEngine.GetService<IManagerAudio2D>().SongVolume * 100.0f).ToString() + "%";
			m_audioMusicValueLabel2.Bounds = new UniRectangle(new UniScalar(0.5f, -0.5f * m_audioMusicValueLabel2.Text.Length * 5.0f), new UniScalar(1.5f, 0.0f), 0, 0);
		}

		private void _SoundSliderMoved(object p_sender, EventArgs p_e) {
			GameEngine.GetService<IManagerAudio2D>().SoundEffectVolume = m_audioSoundVolumeSlider.ThumbPosition;
			m_audioSoundValueLabel2.Text = Math.Floor(GameEngine.GetService<IManagerAudio2D>().SoundEffectVolume * 100.0f).ToString() + "%";
			m_audioSoundValueLabel2.Bounds = new UniRectangle(new UniScalar(0.5f, -0.5f * m_audioSoundValueLabel2.Text.Length * 5.0f), new UniScalar(1.5f, 0.0f), 0, 0);
		}

		private void _ApplyVideoSettings(object p_sender, EventArgs p_e) {
			switch(m_videoResolutionList.SelectedItems[0]) {
				case 0:
					GameEngine.GraphicsDeviceManager.PreferredBackBufferWidth = 800;
					GameEngine.GraphicsDeviceManager.PreferredBackBufferHeight = 600;
					break;
				case 1:
					GameEngine.GraphicsDeviceManager.PreferredBackBufferWidth = 1280;
					GameEngine.GraphicsDeviceManager.PreferredBackBufferHeight = 1024;
					break;
				case 2:
					GameEngine.GraphicsDeviceManager.PreferredBackBufferWidth = 1440;
					GameEngine.GraphicsDeviceManager.PreferredBackBufferHeight = 900;
					break;
			}
			GameEngine.GraphicsDeviceManager.GraphicsDevice.PresentationParameters.MultiSampleCount = m_videoAntialiasingList.SelectedItems[0] * 2;
			GameEngine.GraphicsDeviceManager.PreferMultiSampling = true;
			GameEngine.GraphicsDeviceManager.SynchronizeWithVerticalRetrace = m_videoVsyncOption.Selected;
			GameEngine.GraphicsDeviceManager.IsFullScreen = m_videoFullscreenOption.Selected;

			GameEngine.GraphicsDeviceManager.ApplyChanges();

			GameEngine.GameWindow.BeginScreenDeviceChange(m_videoFullscreenOption.Selected);
			GameEngine.GameWindow.EndScreenDeviceChange(GameEngine.GameWindow.ScreenDeviceName, GameEngine.GraphicsDeviceManager.PreferredBackBufferWidth, GameEngine.GraphicsDeviceManager.PreferredBackBufferHeight);
			GameEngine.GetService<IManagerGUI>().ScreenResolutionChanged();
		}

		#endregion

		#region GUIElement implmentation

		protected override void _Initialize() {
			m_window.EnableDragging = false;
			m_window.Bounds = new UniRectangle(new UniScalar(0.5f, -150.0f), new UniScalar(0.45f, -150.0f), new UniScalar(300.0f), new UniScalar(400));
			m_window.Title = "Options Window";
			_Children.Add(m_window);

			#region main settings window

			m_audioButton.Bounds = new UniRectangle(new UniScalar(0.5f, -75.0f), new UniScalar(0.2f, 0.0f), new UniScalar(150), new UniScalar(40.0f));
			m_audioButton.Text = "Audio Options";
			m_audioButton.Pressed += _ConfigureAudioWindow;

			m_videoButton.Bounds = new UniRectangle(new UniScalar(0.5f, -75.0f), new UniScalar(0.4f, 0.0f), new UniScalar(150), new UniScalar(40.0f));
			m_videoButton.Text = "Video Options";
			m_videoButton.Pressed += _ConfigureVideoWindow;
			m_gameplayButton.Bounds = new UniRectangle(new UniScalar(0.5f, -75.0f), new UniScalar(0.6f, 0.0f), new UniScalar(150), new UniScalar(40.0f));
			m_gameplayButton.Text = "Gameplay Options";
			m_gameplayButton.Pressed += _ConfigureGameplayWindow;

			m_backMainButton.Bounds = new UniRectangle(new UniScalar(0.9f, -55.0f), new UniScalar(0.9f, -12.5f), new UniScalar(55.0f), new UniScalar(25));
			m_backMainButton.Text = "Back";
			m_backMainButton.Pressed += delegate { GameEngine.GetService<IManagerGUI>().RemoveElement(this); };

			#endregion

			m_otherBackButton.Bounds = new UniRectangle(new UniScalar(0.9f, -55.0f), new UniScalar(0.9f, -12.5f), new UniScalar(55.0f), new UniScalar(25));
			m_otherBackButton.Text = "Back";
			m_otherBackButton.Pressed += _ConfigureMainWindow;
			_ConfigureMainWindow(this, null);

			#region audio window

			m_audioMusicVolumeSlider.Bounds = new UniRectangle(new UniScalar(0.5f, -75.0f), new UniScalar(0.3f, 0.0f), new UniScalar(150), new UniScalar(20.0f));
			m_audioMusicVolumeSlider.ThumbSize = 0.1f;
			m_audioMusicVolumeSlider.ThumbPosition = GameEngine.GetService<IManagerAudio2D>().SongVolume;
			m_audioMusicVolumeSlider.Moved += _MusicSliderMoved;

			m_audioMusicValueLabel1.Text = "Music Volume";
			m_audioMusicValueLabel1.Bounds = new UniRectangle(new UniScalar(0.5f, -0.5f * m_audioMusicValueLabel1.Text.Length * 7.0f), new UniScalar(-0.5f, 0.0f), 0, 0);
			m_audioMusicValueLabel2.Text = Math.Floor(GameEngine.GetService<IManagerAudio2D>().SongVolume * 100.0f).ToString() + "%";
			m_audioMusicValueLabel2.Bounds = new UniRectangle(new UniScalar(0.5f, -0.5f * m_audioMusicValueLabel2.Text.Length * 5.0f), new UniScalar(1.5f, 0.0f), 0, 0);

			m_audioMusicVolumeSlider.Children.Add(m_audioMusicValueLabel1);
			m_audioMusicVolumeSlider.Children.Add(m_audioMusicValueLabel2);

			m_audioSoundVolumeSlider.Bounds = new UniRectangle(new UniScalar(0.5f, -75.0f), new UniScalar(0.6f, 0.0f), new UniScalar(150), new UniScalar(20.0f));
			m_audioSoundVolumeSlider.ThumbSize = 0.1f;
			m_audioSoundVolumeSlider.ThumbPosition = GameEngine.GetService<IManagerAudio2D>().SoundEffectVolume;
			m_audioSoundVolumeSlider.Moved += _SoundSliderMoved;

			m_audioSoundValueLabel1.Text = "Sound Effects Volume";
			m_audioSoundValueLabel1.Bounds = new UniRectangle(new UniScalar(0.5f, -0.5f * m_audioSoundValueLabel1.Text.Length * 7.0f), new UniScalar(-0.5f, 0.0f), 0, 0);
			m_audioSoundValueLabel2.Text = Math.Floor(GameEngine.GetService<IManagerAudio2D>().SoundEffectVolume * 100.0f).ToString() + "%";
			m_audioSoundValueLabel2.Bounds = new UniRectangle(new UniScalar(0.5f, -0.5f * m_audioSoundValueLabel2.Text.Length * 5.0f), new UniScalar(1.5f, 0.0f), 0, 0);

			m_audioSoundVolumeSlider.Children.Add(m_audioSoundValueLabel1);
			m_audioSoundVolumeSlider.Children.Add(m_audioSoundValueLabel2);

			#endregion

			#region video window

			m_videoResolutionLabel.Text = "Screen Resolution:";
			m_videoResolutionLabel.Bounds = new UniRectangle(new UniScalar(0.1f, 0.0f), new UniScalar(0.08f, 0.0f), new UniScalar(100.0f), new UniScalar(0.1f, 0.0f));
			m_videoResolutionList.Bounds = new UniRectangle(new UniScalar(0.1f, 0.0f), new UniScalar(0.16f, 0.0f), new UniScalar(0.6f, 0.0f), new UniScalar(0.225f, 0.0f));
			m_videoResolutionList.Items.Add("800 x 600");
			m_videoResolutionList.Items.Add("1280 x 1024");
			m_videoResolutionList.Items.Add("1440 x 900");
			m_videoResolutionList.SelectionMode = ListSelectionMode.Single;

			m_videoFullscreenOption.Text = "Fullscreen";

			m_videoFullscreenOption.Bounds = new UniRectangle(new UniScalar(0.1f, 0.0f), new UniScalar(0.425f, 0.0f), new UniScalar(20.0f), new UniScalar(20.0f));

			m_videoVsyncOption.Text = "Vertical sync refresh rate";

			m_videoVsyncOption.Bounds = new UniRectangle(new UniScalar(0.1f, 0.0f), new UniScalar(0.51f, 0.0f), new UniScalar(20.0f), new UniScalar(20.0f));

			m_videoAntialiasingLabel.Text = "Antialiasing: (does not work)";
			m_videoAntialiasingLabel.Bounds = new UniRectangle(new UniScalar(0.1f, 0.0f), new UniScalar(0.55f, 0.0f), new UniScalar(0.0f), new UniScalar(0.1f, 0.0f));
			m_videoAntialiasingList.Bounds = new UniRectangle(new UniScalar(0.1f, 0.0f), new UniScalar(0.630f, 0.0f), new UniScalar(0.6f, 0.0f), new UniScalar(0.21f, 0.0f));
			m_videoAntialiasingList.Items.Add("none");
			m_videoAntialiasingList.Items.Add("2x");
			m_videoAntialiasingList.Items.Add("4x");
			m_videoAntialiasingList.Items.Add("8x");
			m_videoAntialiasingList.SelectionMode = ListSelectionMode.Single;

			m_videoApplyButton.Bounds = new UniRectangle(new UniScalar(0.2f, -27.5f), new UniScalar(0.9f, -12.5f), new UniScalar(55.0f), new UniScalar(25));
			m_videoApplyButton.Text = "Apply";
			m_videoApplyButton.Pressed += _ApplyVideoSettings;

			#endregion

			#region gameplay window

			#endregion
		}

		protected override void Update(GameTime p_gameTime) {}

		protected override void _Cleanup() {}

		#endregion
	}
}